package com.yfux.cling_player.service.controller;

import static org.fourthline.cling.support.model.TransportAction.Pause;
import static org.fourthline.cling.support.model.TransportAction.Play;
import static org.fourthline.cling.support.model.TransportAction.Seek;
import static org.fourthline.cling.support.model.TransportAction.Stop;

import android.content.Context;

import com.yfux.cling_player.util.LogUtil;

import org.fourthline.cling.model.ModelUtil;
import org.fourthline.cling.support.avtransport.AVTransportException;
import org.fourthline.cling.support.model.DeviceCapabilities;
import org.fourthline.cling.support.model.MediaInfo;
import org.fourthline.cling.support.model.PositionInfo;
import org.fourthline.cling.support.model.StorageMedium;
import org.fourthline.cling.support.model.TransportAction;
import org.fourthline.cling.support.model.TransportInfo;
import org.fourthline.cling.support.model.TransportSettings;
import org.fourthline.cling.support.model.TransportStatus;

public class AVTransportController extends AvTransportControl {
    private static final TransportAction[] TRANSPORT_ACTION_STOPPED = {Play};
    private static final TransportAction[] TRANSPORT_ACTION_PLAYING = {Stop, Pause, Seek};
    private static final TransportAction[] TRANSPORT_ACTION_PAUSE_PLAYBACK = {Play, Seek, Stop};
    RenderControl mediaControl = null;
    private String currentURI;
    private String currentURIMetaData;
    private String nextURI;
    private String nextURIMetaData;
    private String previousURI;
    private String previousURIMetaData;

    public AVTransportController(Context context) {
        applicationContext = context;
        logger = new LogUtil("AVTransportController");
        transportSettings = new TransportSettings();
        deviceCapabilities = new DeviceCapabilities(new StorageMedium[]{StorageMedium.UNKNOWN});
    }

    public void setMediaControl(RenderControl value) {
        if (value != null) {
            mediaInfo = new MediaInfo(currentURI, currentURIMetaData);
            positionInfo = new PositionInfo(0, currentURIMetaData, currentURI);
        } else {
            if (mediaControl != null)
                mediaControl.stop();
            mediaInfo = new MediaInfo();
            positionInfo = new PositionInfo();
        }
        mediaControl = value;
    }

    @Override
    public TransportInfo getTransportInfo() {
        if (mediaControl != null) {
            RenderControl ctrl = mediaControl;
            return new TransportInfo(ctrl.getState().toTransportState(), TransportStatus.OK, "1");
        } else {
            return new TransportInfo();
        }
    }

    @Override
    public MediaInfo getMediaInfo() {
        return mediaInfo;
    }

    @Override
    public PositionInfo getPositionInfo() {
        if (mediaControl != null) {
            RenderControl ctrl = mediaControl;
            String duration = ModelUtil.toTimeString(ctrl.getDuration() / 1000);
            String realTime = ModelUtil.toTimeString(ctrl.getCurrentPosition() / 1000);
            return new PositionInfo(0, duration, currentURI, realTime, realTime);
        } else {
            return new PositionInfo();
        }
    }

    @Override
    public TransportAction[] getCurrentTransportActions() {
        switch (transportInfo.getCurrentTransportState()) {
            case PLAYING:
                return TRANSPORT_ACTION_PLAYING;
            case PAUSED_PLAYBACK:
                return TRANSPORT_ACTION_PAUSE_PLAYBACK;
            default:
                return TRANSPORT_ACTION_STOPPED;
        }
    }

    @Override
    public void setAVTransportURI(String currentURI, String currentURIMetaData) throws AVTransportException {
        super.setAVTransportURI(currentURI, currentURIMetaData);
        this.currentURI = currentURI;
        this.currentURIMetaData = currentURIMetaData;
    }

    @Override
    public void setNextAVTransportURI(String nextURI, String nextURIMetaData) {
        super.setNextAVTransportURI(nextURI, nextURIMetaData);
        this.nextURI = nextURI;
        this.nextURIMetaData = nextURIMetaData;
    }

    @Override
    public void play(String speed) {
        super.play(speed);
        if (mediaControl != null) {
            mediaControl.play(Double.valueOf(speed));
        }
    }

    @Override
    public void pause() {
        super.pause();
        if (mediaControl != null) {
            mediaControl.pause();
        }
    }

    @Override
    public void seek(String unit, String target) {
        super.seek(unit, target);
        try {
            if (mediaControl != null) {
                mediaControl.seek(ModelUtil.fromTimeString(target) * 1000);
            }
        } catch (Exception e) {
            logger.w("seek failed: " + e);
        }
    }

    @Override
    public void next() {
        super.next();
        if (nextURI != null && nextURIMetaData != null) {
            previousURI = currentURI;
            previousURIMetaData = currentURIMetaData;
            try {
                setAVTransportURI(nextURI, nextURIMetaData);
            } catch (AVTransportException e) {
                throw new RuntimeException(e);
            }
        }
        nextURI = null;
        nextURIMetaData = null;
    }

    @Override
    public void previous() {
        super.previous();
        if (previousURI != null && previousURIMetaData != null) {
            nextURI = currentURI;
            nextURIMetaData = currentURIMetaData;
            try {
                setAVTransportURI(previousURI, previousURIMetaData);
            } catch (AVTransportException e) {
                throw new RuntimeException(e);
            }
        }
        previousURI = null;
        previousURIMetaData = null;
    }

    @Override
    public void stop() {
        super.stop();
        if (mediaControl != null) {
            mediaControl.stop();
        }
        mediaInfo = new MediaInfo();
        positionInfo = new PositionInfo();
    }

}